package com.xzy.seckill.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xzy.seckill.common.exception.Assert;
import com.xzy.seckill.common.result.R;
import com.xzy.seckill.common.result.ResponseEnum;
import com.xzy.seckill.pojo.entity.Order;
import com.xzy.seckill.pojo.entity.SeckillGoods;
import com.xzy.seckill.pojo.entity.SeckillOrder;
import com.xzy.seckill.pojo.vo.SeckillGoodDetailVO;
import com.xzy.seckill.service.SeckillGoodsService;
import com.xzy.seckill.service.SeckillOrderService;
import com.xzy.seckill.utils.JwtUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author xzy
 * @since 2022-01-27
 */
@RestController
@RequestMapping("/admin/seckill")
@Api(tags = "秒杀相关接口")
@Slf4j
public class SeckillGoodController {

    @Autowired
    SeckillOrderService seckillOrderService;

    @Autowired
    SeckillGoodsService seckillGoodsService;

    @Autowired
    RedisTemplate redisTemplate;




    @ApiOperation(value = "秒杀接口" )
    @PostMapping("/doSeckill")
    public R doSeckill(HttpServletRequest request,
                        @ApiParam(value = "商品vo", required = true)
                        @RequestBody SeckillGoodDetailVO goods) {

        //解析用户id
        String token = request.getHeader("token");  // 获取令牌(前端将token放入请求头中)
        Integer userId = JwtUtils.getUserId(token);     //解析出token中的用户id


        //内存标记 这里为简单第一次校验，无法保证原子性，目的是增加并发量，
        // 真正安全的库存校验还是得使用redis原子操作，这里的操作类比与单例模式双重检查加锁的第一道锁
        Map<String, Boolean> sotckTag = seckillOrderService.getSotckTag();
        Boolean tag = sotckTag.get(goods.getId().toString());
        if(null!=tag&&!tag){
            //库存不足
            //log.info("内存标记校验库存不足");
            Assert.isTrue(false,ResponseEnum.EMPTY_STOCK);
        }


        //校验是否重复下单
        seckillOrderService.checkOrder(userId,goods.getId());

        //执行操作
        Order order = seckillOrderService.doSeckill2(userId, goods);

        return R.ok().message("下单成功").data("order",order);
    }


    /**
     * 秒杀初始化操作
     * 1 将原始库存信息从mysql存入redis
     * 2 初始化内存标记
     * @return
     */
    @ApiOperation(value = "初始化秒杀" )
    @PostMapping("/Init")
    public R Init(){
        IPage<SeckillGoodDetailVO> list = seckillGoodsService.list(new Page<>(0, -1));
        List<SeckillGoodDetailVO> records = list.getRecords();
        records.stream().forEach((e)->{
            redisTemplate.opsForValue().set( "sec:product:stock:"+e.getId(),e.getStockCount());

            //添加内存标记
            Map<String, Boolean> sotckTag = seckillOrderService.getSotckTag();
            sotckTag.put(e.getId().toString(),e.getStockCount()>0);
        });
        return R.ok().message("操作成功");
    }



}

